//
//  CCCamera.cpp
//  ShadowMapping
//
//  Created by Daniel Corleone on 18/6/14.
//  Copyright (c) 2014年 iCloverStudio. All rights reserved.
//

#include "CCCamera.h"

BECO_NAMESPACE_BEGIN

Camera::Camera(const String& name, Camera_Type type)
: Node(eCamera, name)
, eCameraType(type)
, vEye(glm::zero<glm::vec3>())
, vTarget(glm::zero<glm::vec3>())
, vUp(glm::zero<glm::vec3>())
, matProjection(glm::zero<glm::mat4>())
, rAngle(0.0)
, rAspectRatio(0)
, rNear(0)
, rFar(0)
{
}

Camera::Camera(Node* parentNode, const String& name, Camera_Type type)
: Node(eCamera, parentNode, name)
, eCameraType(type)
, vEye(glm::zero<glm::vec3>())
, vTarget(glm::zero<glm::vec3>())
, vUp(glm::zero<glm::vec3>())
, matProjection(glm::zero<glm::mat4>())
, rAngle(0.0)
, rAspectRatio(0)
, rNear(0)
, rFar(0)
{
}

Camera::~Camera()
{
}

CC_INLINE void
Camera::setupPerspective(const Real angle, const Real aspectRatio, const Real clipNear, const Real clipFar)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    if (eCameraType == CAMERA_TYPE_PERSPECTIVE) {
        Real rfov = angle * glm::pi<Real>() / 180.0;
		glm::mat4 matCamera = glm::perspective(rfov, aspectRatio, clipNear, clipFar);
        
        glLoadMatrixf(glm::value_ptr(matCamera));
    }
    else if (eCameraType == CAMERA_TYPE_ORTHO) {
        
    }
    
    return;
}

CC_INLINE void
Camera::setupLookat(const Real eyeX, const Real eyeY, const Real eyeZ, const Real targetX, const Real targetY, const Real targetZ, const Real upX, const Real upY, const Real upZ)
{
    /// refreshing all vector & matrix for camera view.
    vEye = glm::vec3(eyeX, eyeY, eyeZ);
    vTarget = glm::vec3(targetX, targetY, targetZ);
    vUp = glm::vec3(upX, upY, upZ);
    matProjection = glm::lookAt(vEye, vTarget, vUp);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glLoadMatrixf(glm::value_ptr(matProjection));
    
    return;
}

CC_INLINE glm::mat4
Camera::getProjectMatrix(void) const
{
    return matProjection;
}

CC_INLINE glm::vec3
Camera::getCameraPosition() const {
    return glm::vec3(vEye);
}

CC_INLINE glm::vec3
Camera::getTarget() const {
    return glm::vec3(vTarget);
}

CC_INLINE glm::vec3
Camera::getUp() const {
    return glm::vec3(vUp);
}

CC_INLINE void Camera::Update(const Real timeInterval)
{
    return;
}

CC_INLINE void Camera::Render(const Real timeInterval)
{
    setupPerspective(rAngle, rAspectRatio, rNear, rFar);
    setupLookat(vEye.x, vEye.y, vEye.z, vTarget.x, vTarget.y, vTarget.z, vUp.x, vUp.y, vUp.z);
    return;
}

BECO_NAMESPACE_END
